package dsk.demo.product.config;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import dsk.demo.product.dao.GMessageDao;
import dsk.demo.product.dao.GWeekPriceDao;
import dsk.demo.product.entity.gupiao.GMessage;
import dsk.demo.product.entity.gupiao.GWeekPrice;
import dsk.demo.product.util.CacheUtil;
import dsk.demo.product.util.QiyeVxUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class TonghuashunJob {


    private static String refresh_token = "eyJzaWduX3RpbWUiOiIyMDI1LTA5LTAzIDIxOjI5OjIzIn0=.eyJ1aWQiOiI3NTAzOTk1MDEiLCJ1c2VyIjp7ImFjY291bnQiOiJteF8xanZqbHFlcmsiLCJhdXRoVXNlckluZm8iOnt9LCJjb2RlQ1NJIjpbXSwiY29kZVp6QXV0aCI6W10sImhhc0FJUHJlZGljdCI6ZmFsc2UsImhhc0FJVGFsayI6ZmFsc2UsImhhc0NJQ0MiOmZhbHNlLCJoYXNDU0kiOmZhbHNlLCJoYXNFdmVudERyaXZlIjpmYWxzZSwiaGFzRlRTRSI6ZmFsc2UsImhhc0Zhc3QiOmZhbHNlLCJoYXNGdW5kVmFsdWF0aW9uIjpmYWxzZSwiaGFzSEsiOnRydWUsImhhc0xNRSI6ZmFsc2UsImhhc0xldmVsMiI6ZmFsc2UsImhhc1JlYWxDTUUiOmZhbHNlLCJoYXNUcmFuc2ZlciI6ZmFsc2UsImhhc1VTIjpmYWxzZSwiaGFzVVNBSW5kZXgiOmZhbHNlLCJoYXNVU0RFQlQiOmZhbHNlLCJtYXJrZXRBdXRoIjp7IkRDRSI6ZmFsc2V9LCJtYXhPbkxpbmUiOjEsIm5vRGlzayI6ZmFsc2UsInByb2R1Y3RUeXBlIjoiU1VQRVJDT01NQU5EUFJPRFVDVCIsInJlZnJlc2hUb2tlbiI6IiIsInJlZnJlc2hUb2tlbkV4cGlyZWRUaW1lIjoiMjAyNS0wOS0xMCAxOTozOTowMCIsInNlc3NzaW9uIjoiYzFjMTdjN2M3ODNjYzIwN2VkN2I0YzcxYmE4NTZjMDQiLCJzaWRJbmZvIjp7NjQ6IjExMTExMTExMTExMTExMTExMTExMTExMSIsMToiMTAxIiwyOiIxIiw2NzoiMTAxMTExMTExMTExMTExMTExMTExMTExIiwzOiIxIiw2OToiMTExMTExMTExMTExMTExMTExMTExMTExMSIsNToiMSIsNjoiMSIsNzE6IjExMTExMTExMTExMTExMTExMTExMTEwMCIsNzoiMTExMTExMTExMTEiLDg6IjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxIiwxMzg6IjExMTExMTExMTExMTExMTExMTExMTExMTEiLDEzOToiMTExMTExMTExMTExMTExMTExMTExMTExMSIsMTQwOiIxMTExMTExMTExMTExMTExMTExMTExMTExIiwxNDE6IjExMTExMTExMTExMTExMTExMTExMTExMTEiLDE0MjoiMTExMTExMTExMTExMTExMTExMTExMTExMSIsMTQzOiIxMSIsODA6IjExMTExMTExMTExMTExMTExMTExMTExMSIsODE6IjExMTExMTExMTExMTExMTExMTExMTExMSIsODI6IjExMTExMTExMTExMTExMTExMTExMDExMCIsODM6IjExMTExMTExMTExMTExMTExMTAwMDAwMCIsODU6IjAxMTExMTExMTExMTExMTExMTExMTExMSIsODc6IjExMTExMTExMDAxMTExMTAxMTExMTExMSIsODk6IjExMTExMTExMDExMDEwMDAwMDAwMTExMSIsOTA6IjExMTExMDExMTExMTExMTExMDAwMTExMTEwIiw5MzoiMTExMTExMTExMTExMTExMTEwMDAwMTExMSIsOTQ6IjExMTExMTExMTExMTExMTExMTExMTExMTEiLDk2OiIxMTExMTExMTExMTExMTExMTExMTExMTExIiw5OToiMTAwIiwxMDA6IjExMTEwMTExMTExMTExMTExMTAiLDEwMjoiMSIsNDQ6IjExIiwxMDk6IjEiLDUzOiIxMTExMTExMTExMTExMTExMTExMTExMTEiLDU0OiIxMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCIsNTc6IjAwMDAwMDAwMDAwMDAwMDAwMDAwMTAwMDAwMDAwIiw2MjoiMTExMTExMTExMTExMTExMTExMTExMTExIiw2MzoiMTExMTExMTExMTExMTExMTExMTExMTExIn0sInRpbWVzdGFtcCI6IjE3NTY5MDYxNjMxNjUiLCJ0cmFuc0F1dGgiOmZhbHNlLCJ0dGxWYWx1ZSI6MCwidWlkIjoiNzUwMzk5NTAxIiwidXNlclR5cGUiOiJGUkVFSUFMIiwid2lmaW5kTGltaXRNYXAiOnt9fX0=.1F2C39AA7FEB3DC8B1C739531E3962382B06A5C3723C19C8271E8811475D454C";

    private static String corpid = "ww730e1bd4b63f4a14";
    private static String corpsecret = "qi6AnjZ4T5E5G_o7BJneyXqvso-uFkb-pGtMGq9nwPk";
    private static String agentId = "1000002";

    private static List<String> PUSH_LIST = Arrays.asList(new String[]{"DaiShiKun", "ChenDong"});

    @Autowired
    private GWeekPriceDao weekPriceDao;
    @Autowired
    private GMessageDao messageDao;
    @Autowired
    private QiyeVxUtil qiyeVxUtil;


    // 每天早上更新周线价格,  盘中更新收盘价, 然后计算是否需要触发结果
    @Scheduled(cron = "0 0/5 9,10,11,13,14 * * MON-FRI")
    public void TengxunJob() {
        try {

            String ret = HttpUtil.get("https://sqt.gtimg.cn/q=sh512890");

            String result = ret.split("\"")[1];
            String[] split = result.split("~");
            // 盘中实时价格
            // 20250905161447
            DateTime yyyyMMddHHmmss = DateUtil.parse(split[30], "yyyyMMddHHmmss");
            DateTime dateTime = DateUtil.beginOfDay(yyyyMMddHHmmss);
            DateTime today = DateUtil.beginOfDay(new Date());
            DateTime weekFirstDay = DateUtil.beginOfWeek(new Date());
            DateUtil.offsetMinute(DateUtil.offsetHour(today, 9), 5);

            // 等同每天9点推送消息
            if (new Date().before(DateUtil.offsetMinute(DateUtil.offsetHour(today, 9), 5))) {
                GWeekPrice zuori = weekPriceDao.selectOne(Wrappers.<GWeekPrice>lambdaQuery()
                        .orderByDesc(GWeekPrice::getTime)
                        .last("limit 1")
                );
                qiyeVxUtil.sendMail("今日行情即将开始, 昨日数据...\n" +
                                "昨日收盘: " + zuori.getThsCloseWFund() +
                                "昨日55周均价:" + zuori.getAvg55() + ", \n" +
                                "今日RIS(6)值:" + zuori.getRsi6() + "\n",
                        Collections.singletonList("DaiShiKun"));
            }

            // 是同一天, 代表当天行情开始
            if (DateUtil.isSameDay(today, dateTime)) {
                GWeekPrice gWeekPrice = weekPriceDao.selectOne(Wrappers.<GWeekPrice>lambdaQuery().ge(GWeekPrice::getTime, weekFirstDay));
                GWeekPrice oneWeekAgo = weekPriceDao.selectOne(Wrappers.<GWeekPrice>lambdaQuery()
                        .lt(GWeekPrice::getTime, weekFirstDay)
                        .orderByDesc(GWeekPrice::getTime)
                        .last("limit 1")
                );
                if (gWeekPrice != null) {
                    // 不是本周第一天或数据已存在 , 直接用 这个数据的收盘价, 来计算rsi和涨跌幅
                    gWeekPrice.setTime(today);
                    gWeekPrice.setThsCloseWFund(new BigDecimal(split[3]));
                    gWeekPrice.setThsHighWFund(max(new BigDecimal(split[33]), gWeekPrice.getThsHighWFund()));
                    if (gWeekPrice.getThsLowWFund().compareTo(new BigDecimal(0)) == 0) {
                        gWeekPrice.setThsLowWFund(new BigDecimal(split[34]));
                    } else {
                        gWeekPrice.setThsLowWFund(min(new BigDecimal(split[34]), gWeekPrice.getThsLowWFund()));
                    }

                    gWeekPrice.setThsChgWFund(gWeekPrice.getThsCloseWFund().subtract(oneWeekAgo.getThsCloseWFund()));
                    gWeekPrice.setThsChgRatioWFund(gWeekPrice.getThsCloseWFund().subtract(oneWeekAgo.getThsCloseWFund())
                            .divide(oneWeekAgo.getThsCloseWFund(), 6, RoundingMode.HALF_UP)
                            .multiply(new BigDecimal("100")));
                    weekPriceDao.updateById(gWeekPrice);
                } else {
                    // 是本周第一天, 且数据还没第一次插入
                    // 所有的数据就是本周数据
                    GWeekPrice lastData = GWeekPrice.builder()
                            .thscode("512890.SH")
                            .time(today)
                            .thsOpenWFund(new BigDecimal(split[5]))
                            .thsCloseWFund(new BigDecimal(split[3]))
                            .thsHighWFund(new BigDecimal(split[33]))
                            .thsLowWFund(new BigDecimal(split[34]))
                            .build();
                    lastData.setThsChgWFund(lastData.getThsCloseWFund().subtract(oneWeekAgo.getThsCloseWFund()));
                    lastData.setThsChgRatioWFund(lastData.getThsCloseWFund().subtract(oneWeekAgo.getThsCloseWFund())
                            .divide(oneWeekAgo.getThsCloseWFund(), 6, RoundingMode.HALF_UP)
                            .multiply(new BigDecimal("100")));
                    weekPriceDao.insert(lastData);
                }
                // 处理完之后处理 技术指标
                dealTodayAg();
                dealTodayRsi();
                // 判断是否需要预警
                gWeekPrice = weekPriceDao.selectOne(Wrappers.<GWeekPrice>lambdaQuery()
                        .orderByDesc(GWeekPrice::getTime)
                        .last("limit 1")
                );
                if (gWeekPrice != null) {
                    checkAndSendMail(gWeekPrice);
                }
            }
        } catch (Exception e) {
            log.error("报错信息:[{}]", e);
            qiyeVxUtil.sendMail("执行报错了....", Collections.singletonList("DaiShiKun"));
        }


    }

    /**
     * 每个周一到周五下午15点5分更新当天的周线
     */
    @Scheduled(cron = "0 5 15 * * MON-FRI")
    public void TengxunGetWeekEnd() {
        String ret = HttpUtil.get("https://proxy.finance.qq.com/ifzqgtimg/appstock/app/newfqkline/get?param=sh512890,week,,,320,qfq&type=qfq&_var=kline_weekqfq");
        JSONObject object = JSONUtil.parseObj(ret.split("=")[1]);
        JSONArray jsonArray = object.getJSONObject("data").getJSONObject("sh512890").getJSONArray("qfqweek");


        // 最新一周的数据
        JSONArray lastData = (JSONArray) jsonArray.get(jsonArray.size() - 1);
        // 一周前数据
        JSONArray oneWeekAgo = (JSONArray) jsonArray.get(jsonArray.size() - 2);

        GWeekPrice build = GWeekPrice.builder()
                .thscode("512890.SH")
                .time(lastData.getDate(0))
                .thsOpenWFund(lastData.getBigDecimal(1))
                .thsCloseWFund(lastData.getBigDecimal(2))
                .thsHighWFund(lastData.getBigDecimal(3))
                .thsLowWFund(lastData.getBigDecimal(4))
                .thsChgWFund(lastData.getBigDecimal(2).subtract(oneWeekAgo.getBigDecimal(2)))
                .thsChgRatioWFund(lastData.getBigDecimal(2).subtract(oneWeekAgo.getBigDecimal(2))
                        .divide(oneWeekAgo.getBigDecimal(2), 6, RoundingMode.HALF_UP)
                        .multiply(new BigDecimal("100")))
                .build();

        DateTime dateTime = DateUtil.beginOfWeek(build.getTime());
        GWeekPrice gWeekPrice = weekPriceDao.selectOne(Wrappers.<GWeekPrice>lambdaQuery().ge(GWeekPrice::getTime, dateTime));
        if (gWeekPrice != null) {
            build.setId(gWeekPrice.getId());
            log.info("本周数据已存在, 即将更新");
            weekPriceDao.updateById(build);
        } else {
            weekPriceDao.insert(build);
        }

        List<GWeekPrice> gWeekPrices = weekPriceDao.selectList(Wrappers.<GWeekPrice>lambdaQuery()
                .orderByDesc(GWeekPrice::getTime)
                .last("limit 56")
        );

        BigDecimal nianhua = gWeekPrices.get(0).getAvg55().subtract(gWeekPrices.get(gWeekPrices.size() - 1).getAvg55())
                .divide(gWeekPrices.get(gWeekPrices.size() - 1).getAvg55(), 6, RoundingMode.HALF_UP)
                .multiply(new BigDecimal(100));

        BigDecimal junxianpianli = gWeekPrices.get(0).getThsCloseWFund().subtract(gWeekPrices.get(0).getAvg55()).divide(gWeekPrices.get(0).getAvg55(),
                6, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
        BigDecimal waitTime = junxianpianli.multiply(new BigDecimal("56")).divide(nianhua, 2, RoundingMode.HALF_UP);
        int i = waitTime.intValue() / 2;

        qiyeVxUtil.sendMail("当天行情已结束\n" +
                        "红利低波ETF收盘价:" + gWeekPrices.get(0).getThsCloseWFund() + ", \n" +
                        "今日55周均价:" + gWeekPrices.get(0).getAvg55() + ", \n" +
                        "偏离均线值:" + junxianpianli + "% , \n" +
                        "今日RIS(6)值:" + gWeekPrices.get(0).getRsi6() + ", \n" +
                        "如果在下行阶段, 预估还有" + i + "周可买入."
                , PUSH_LIST);
    }

    public void checkAndSendMail(GWeekPrice gWeekPrice) {
        // 避免当日重复推送
        if (gWeekPrice.getRsi6().compareTo(new BigDecimal("25")) < 0 &&
                gWeekPrice.getThsLowWFund().compareTo(gWeekPrice.getAvg55().multiply(new BigDecimal("1"))) < 0
        ) {
            GMessage buy = messageDao.selectOne(Wrappers.<GMessage>lambdaQuery()
                    .eq(GMessage::getDate, DateUtil.beginOfDay(new Date()))
                    .eq(GMessage::getLevel, 1)
                    .eq(GMessage::getType, "买")
            );
            if (buy == null) {
                qiyeVxUtil.sendMail(getMessageInfo(gWeekPrice, "建议全仓买入"), PUSH_LIST);
                messageDao.insert(GMessage.builder()
                        .date(DateUtil.beginOfDay(new Date()))
                        .level(1)
                        .type("买")
                        .message(getMessageInfo(gWeekPrice, "建议全仓买入"))
                        .build());
            }
        } else if (gWeekPrice.getRsi6().compareTo(new BigDecimal("30")) < 0 &&
                gWeekPrice.getThsLowWFund().compareTo(gWeekPrice.getAvg55().multiply(new BigDecimal("1.02"))) < 0
        ) {
            GMessage buy = messageDao.selectOne(Wrappers.<GMessage>lambdaQuery()
                    .eq(GMessage::getDate, DateUtil.beginOfDay(new Date()))
                    .eq(GMessage::getLevel, 2)
                    .eq(GMessage::getType, "买")
            );
            if (buy == null) {
                qiyeVxUtil.sendMail(getMessageInfo(gWeekPrice, "建议中等仓位买入 1/10"), PUSH_LIST);
                messageDao.insert(GMessage.builder()
                        .date(DateUtil.beginOfDay(new Date()))
                        .level(2)
                        .type("买")
                        .message(getMessageInfo(gWeekPrice, "建议中等仓位买入 1/10"))
                        .build());
            }
        } else if (gWeekPrice.getRsi6().compareTo(new BigDecimal("35")) < 0 &&
                gWeekPrice.getThsLowWFund().compareTo(gWeekPrice.getAvg55().multiply(new BigDecimal("1.04"))) < 0) {
            GMessage buy = messageDao.selectOne(Wrappers.<GMessage>lambdaQuery()
                    .eq(GMessage::getDate, DateUtil.beginOfDay(new Date()))
                    .eq(GMessage::getLevel, 3)
                    .eq(GMessage::getType, "买")
            );
            if (buy == null) {
                qiyeVxUtil.sendMail(getMessageInfo(gWeekPrice, "建议小仓位买入 1/20"), PUSH_LIST);
                messageDao.insert(GMessage.builder()
                        .date(DateUtil.beginOfDay(new Date()))
                        .level(3)
                        .type("买")
                        .message(getMessageInfo(gWeekPrice, "建议小仓位买入 1/20"))
                        .build());
            }
        }
        // 价格偏离55周线 12% 提示卖出
        if (gWeekPrice.getRsi6().compareTo(new BigDecimal("80")) > 0 &&
                gWeekPrice.getThsHighWFund().compareTo(gWeekPrice.getAvg55().multiply(new BigDecimal("1.16"))) > 0) {
            GMessage sell = messageDao.selectOne(Wrappers.<GMessage>lambdaQuery()
                    .eq(GMessage::getDate, DateUtil.beginOfDay(new Date()))
                    .eq(GMessage::getLevel, 1)
                    .eq(GMessage::getType, "卖")
            );
            if (sell == null) {
                qiyeVxUtil.sendMail(getMessageInfo(gWeekPrice, "建议全仓卖出"), PUSH_LIST);
                messageDao.insert(GMessage.builder()
                        .date(DateUtil.beginOfDay(new Date()))
                        .level(1)
                        .type("卖")
                        .message(getMessageInfo(gWeekPrice, "建议全仓卖出"))
                        .build());
            }
        } else if (gWeekPrice.getRsi6().compareTo(new BigDecimal("73")) > 0 &&
                gWeekPrice.getThsHighWFund().compareTo(gWeekPrice.getAvg55().multiply(new BigDecimal("1.12"))) > 0) {
            GMessage sell = messageDao.selectOne(Wrappers.<GMessage>lambdaQuery()
                    .eq(GMessage::getDate, DateUtil.beginOfDay(new Date()))
                    .eq(GMessage::getLevel, 2)
                    .eq(GMessage::getType, "卖")
            );
            if (sell == null) {
                qiyeVxUtil.sendMail(getMessageInfo(gWeekPrice, "建议中仓位卖出 1/10"), PUSH_LIST);
                messageDao.insert(GMessage.builder()
                        .date(DateUtil.beginOfDay(new Date()))
                        .level(2)
                        .type("卖")
                        .message(getMessageInfo(gWeekPrice, "建议中仓位卖出 1/10"))
                        .build());
            }
        } else if (gWeekPrice.getRsi6().compareTo(new BigDecimal("65")) > 0 &&
                gWeekPrice.getThsHighWFund().compareTo(gWeekPrice.getAvg55().multiply(new BigDecimal("1.10"))) > 0) {
            GMessage sell = messageDao.selectOne(Wrappers.<GMessage>lambdaQuery()
                    .eq(GMessage::getDate, DateUtil.beginOfDay(new Date()))
                    .eq(GMessage::getLevel, 3)
                    .eq(GMessage::getType, "卖")
            );
            if (sell == null) {
                qiyeVxUtil.sendMail(getMessageInfo(gWeekPrice, "建议小仓位卖出 1/20"), PUSH_LIST);
                messageDao.insert(GMessage.builder()
                        .date(DateUtil.beginOfDay(new Date()))
                        .level(3)
                        .type("卖")
                        .message(getMessageInfo(gWeekPrice, "建议小仓位卖出 1/20"))
                        .build());
            }
        }
    }

    private String getMessageInfo(GWeekPrice gWeekPrice, String advice) {
        return "红利低波当前价格触发买卖提醒"
                + ",\n 日期:" + DateUtil.format(gWeekPrice.getTime(), "yyyy-MM-dd")
                + ",\n " + advice
                + ",\n 当前股价:" + gWeekPrice.getThsCloseWFund()
                + ",\n ris6值: " + gWeekPrice.getRsi6()
                + ",\n 相对55均线涨跌幅: " + gWeekPrice.getThsCloseWFund()
                .subtract(gWeekPrice.getAvg55()).divide(gWeekPrice.getAvg55(), 6, RoundingMode.HALF_UP)
                .multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP) + "%";
    }


    public void dealTodayAg() {
        List<GWeekPrice> gWeekPrices = weekPriceDao.selectList(Wrappers.<GWeekPrice>lambdaQuery()
                .last("limit 55")
                .orderByDesc(GWeekPrice::getTime));
        for (int i = 0; i < gWeekPrices.size(); i++) {
            if (i + 55 <= gWeekPrices.size()) {
                List<GWeekPrice> sub = CollectionUtil.sub(gWeekPrices, i, i + 55);
                BigDecimal avg55 = sub.stream().map(GWeekPrice::getThsCloseWFund).reduce(BigDecimal.ZERO, BigDecimal::add)
                        .divide(new BigDecimal(55), RoundingMode.HALF_UP).setScale(3, RoundingMode.HALF_UP);
                gWeekPrices.get(i).setAvg55(avg55);
            }
        }
        weekPriceDao.updateById(gWeekPrices.get(0));
    }


    public void dealAg() {
        List<GWeekPrice> gWeekPrices = weekPriceDao.selectList(Wrappers.<GWeekPrice>lambdaQuery().orderByDesc(GWeekPrice::getTime));
        for (int i = 0; i < gWeekPrices.size(); i++) {
            if (i + 55 < gWeekPrices.size()) {
                List<GWeekPrice> sub = CollectionUtil.sub(gWeekPrices, i, i + 55);
                BigDecimal avg55 = sub.stream().map(GWeekPrice::getThsCloseWFund).reduce(BigDecimal.ZERO, BigDecimal::add)
                        .divide(new BigDecimal(55), RoundingMode.HALF_UP).setScale(3, RoundingMode.HALF_UP);
                gWeekPrices.get(i).setAvg55(avg55);
            }
        }
        weekPriceDao.replaceBatch(gWeekPrices);
        System.out.println(JSONUtil.toJsonStr(gWeekPrices, JSONConfig.create().setDateFormat("yyyy-MM-dd")));
    }

    public void dealTodayRsi() {
        List<GWeekPrice> gWeekPrices = weekPriceDao.selectList(Wrappers.<GWeekPrice>lambdaQuery()
                .last("limit 6")
                .orderByDesc(GWeekPrice::getTime)
        );
        gWeekPrices.sort((a, b) -> a.getTime().compareTo(b.getTime()));
        for (int i = 6; i <= gWeekPrices.size(); i++) {
            List<GWeekPrice> sub = CollectionUtil.sub(gWeekPrices, i - 6, i);
            // 平滑移动平均法
            BigDecimal X = max(sub.get(5).getThsCloseWFund().subtract(sub.get(4).getThsCloseWFund()), BigDecimal.ZERO);
            BigDecimal AU = X.add(sub.get(4).getRsi6zhangfu().multiply(new BigDecimal(5))).divide(new BigDecimal(6), 4, RoundingMode.HALF_UP);

            BigDecimal X2 = min(sub.get(5).getThsCloseWFund().subtract(sub.get(4).getThsCloseWFund()), BigDecimal.ZERO).abs();
            BigDecimal DU = X2.add(sub.get(4).getRsi6diefu().multiply(new BigDecimal(5))).divide(new BigDecimal(6), 4, RoundingMode.HALF_UP);
            BigDecimal RSI = getRSI(AU, DU);
            sub.get(5).setRsi6(RSI);
            sub.get(5).setRsi6zhangfu(AU);
            sub.get(5).setRsi6diefu(DU);
        }
        weekPriceDao.updateById(gWeekPrices.get(5));
    }


    public void dealRsi() {
        List<GWeekPrice> gWeekPrices = weekPriceDao.selectList(Wrappers.<GWeekPrice>lambdaQuery().orderByAsc(GWeekPrice::getTime));

        for (int i = 6; i <= gWeekPrices.size(); i++) {
            List<GWeekPrice> sub = CollectionUtil.sub(gWeekPrices, i - 6, i);
            if (i == 6) {
                // 6日平均涨幅/ 6日平均跌幅
                List<GWeekPrice> zhangfu = sub.stream().filter(item -> item.getThsChgRatioWFund().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
                List<GWeekPrice> diefu = sub.stream().filter(item -> item.getThsChgRatioWFund().compareTo(BigDecimal.ZERO) < 0).collect(Collectors.toList());

                BigDecimal AU = BigDecimal.ZERO;
                if (zhangfu.size() > 0) {
                    AU = zhangfu.stream().map(GWeekPrice::getThsChgRatioWFund).reduce(BigDecimal.ZERO, BigDecimal::add)
                            .divide(new BigDecimal(6), 4, RoundingMode.HALF_UP).setScale(4, RoundingMode.HALF_UP);
                }

                BigDecimal DU = BigDecimal.ZERO;
                if (zhangfu.size() > 0) {
                    DU = diefu.stream().map(GWeekPrice::getThsChgRatioWFund).reduce(BigDecimal.ZERO, BigDecimal::add)
                            .divide(new BigDecimal(6), 4, RoundingMode.HALF_UP).setScale(4, RoundingMode.HALF_UP).abs();
                }
                BigDecimal RSI = getRSI(AU, DU);
                sub.get(5).setRsi6(RSI);
                sub.get(5).setRsi6zhangfu(AU);
                sub.get(5).setRsi6diefu(DU);
            } else {
                // 平滑移动平均法
                BigDecimal X = max(sub.get(5).getThsCloseWFund().subtract(sub.get(4).getThsCloseWFund()), BigDecimal.ZERO);
                BigDecimal AU = X.add(sub.get(4).getRsi6zhangfu().multiply(new BigDecimal(5))).divide(new BigDecimal(6), 4, RoundingMode.HALF_UP);

                BigDecimal X2 = min(sub.get(5).getThsCloseWFund().subtract(sub.get(4).getThsCloseWFund()), BigDecimal.ZERO).abs();
                BigDecimal DU = X2.add(sub.get(4).getRsi6diefu().multiply(new BigDecimal(5))).divide(new BigDecimal(6), 4, RoundingMode.HALF_UP);
                BigDecimal RSI = getRSI(AU, DU);
                sub.get(5).setRsi6(RSI);
                sub.get(5).setRsi6zhangfu(AU);
                sub.get(5).setRsi6diefu(DU);
            }
        }

        System.out.println(JSONUtil.toJsonStr(gWeekPrices, JSONConfig.create().setDateFormat("yyyy-MM-dd")));
        weekPriceDao.replaceBatch(gWeekPrices);
    }


    private BigDecimal max(BigDecimal a, BigDecimal b) {
        if (a.compareTo(b) > 0) {
            return a;
        } else {
            return b;
        }
    }

    private BigDecimal min(BigDecimal a, BigDecimal b) {
        if (a.compareTo(b) > 0) {
            return b;
        } else {
            return a;
        }
    }

    // A上涨  DU下跌
    private BigDecimal getRSI(BigDecimal AU, BigDecimal DU) {
        if (AU.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        } else if (DU.compareTo(BigDecimal.ZERO) == 0) {
            return new BigDecimal("100");
        }
        try {
            return new BigDecimal("100").subtract(
                    new BigDecimal("100").divide(new BigDecimal("1").add(AU.divide(DU, 4, RoundingMode.HALF_UP)), 4, RoundingMode.HALF_UP)
            );
        } catch (Exception e) {
            e.printStackTrace();
        }
        return BigDecimal.ZERO;
    }

//
//    private static String getAccessToken() {
//        String body = HttpUtil.createGet("https://ft.10jqka.com.cn/api/v1/get_access_token")
//                .header("Content-Type", "application/json")
//                .header("refresh_token", refresh_token)
//                .execute().body();
//        String str = JSONUtil.parseObj(body).getJSONObject("data").getStr("access_token");
//        if (StrUtil.isBlank(str)) {
//            // 更新token
//            HttpUtil.createGet("https://ft.10jqka.com.cn/api/v1/update_access_token")
//                    .header("Content-Type", "application/json")
//                    .header("refresh_token", refresh_token)
//                    .execute().body();
//            return str;
//        }
//        return str;
//    }


}
